refs: add "ostree refs --create" and unit tests
authorYu Qi Zhang <jzehrarnyg@gmail.com>
Tue, 14 Jun 2016 14:13:06 +0000 (14:13 +0000)
committerAtomic Bot <atomic-devel@projectatomic.io>
Wed, 15 Jun 2016 20:42:30 +0000 (20:42 +0000)
Added the ability to create a ref (much like a git tag) for an
existing commit through "ostree refs EXISTING --create=NEWREF".
Previously the only way to create a new ref was by creating a new commit,
but refs --create allows multiple refs to point to the same commit.

The command will fail if:
 - None/more than one existing ref is specified
 - The specified EXISTING tag does not exist, or was not specified
 - The specified NEWREF already exists, or is the name of a folder

Add unit tests in tests-ref.sh to verify above functionality

Closes: #340
Approved by: jlebon

src/ostree/ot-builtin-refs.c
tests/test-refs.sh

index af90c841e9767ae79654465b716c4720f0cb5df5..10647ec639e038dbea208e856c26e32e65dfb7c7 100644 (file)
 
 static gboolean opt_delete;
 static gboolean opt_list;
+static char *opt_create;
 
 static GOptionEntry options[] = {
   { "delete", 0, 0, G_OPTION_ARG_NONE, &opt_delete, "Delete refs which match PREFIX, rather than listing them", NULL },
   { "list", 0, 0, G_OPTION_ARG_NONE, &opt_list, "Do not remove the prefix from the refs", NULL },
+  { "create", 0, 0, G_OPTION_ARG_STRING, &opt_create, "Create a new ref for an existing commit", "NEWREF" },
   { NULL }
 };
 
@@ -48,10 +50,16 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
                                       cancellable, error))
         goto out;
     }
+  else if (opt_create)
+    {
+      if (!ostree_repo_list_refs_ext (repo, NULL, &refs, OSTREE_REPO_LIST_REFS_EXT_NONE,
+                                      cancellable, error))
+        goto out;
+    }
   else if (!ostree_repo_list_refs (repo, refspec_prefix, &refs, cancellable, error))
     goto out;
 
-  if (!opt_delete)
+  if (!opt_delete && !opt_create)
     {
       g_hash_table_iter_init (&hashiter, refs);
       while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
@@ -60,7 +68,30 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
           g_print ("%s\n", ref);
         }
     }
+  else if (opt_create)
+    {
+      g_autofree char *checksum = NULL;
+      g_autofree char *checksum_existing = NULL;
+
+      if (!ostree_repo_resolve_rev (repo, opt_create, TRUE, &checksum_existing, error))
+        goto out;
+
+      if (checksum_existing != NULL)
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "--create specified but ref %s already exists", opt_create);
+          goto out;
+        }
+
+      if (!ostree_repo_resolve_rev (repo, refspec_prefix, FALSE, &checksum, error))
+        goto out;
+
+      if (!ostree_repo_set_ref_immediate (repo, NULL, opt_create, checksum,
+                                          cancellable, error))
+        goto out;
+    }
   else
+    /* delete */
     {
       g_hash_table_iter_init (&hashiter, refs);
       while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
@@ -97,6 +128,12 @@ ostree_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError **
 
   if (argc >= 2)
     {
+      if (opt_create && argc > 2)
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "You must specify only 1 existing ref when creating a new ref");
+          goto out;
+        }
       for (i = 1; i < argc; i++)
         if (!do_ref (repo, argv[i], cancellable, error))
           goto out;
@@ -110,6 +147,13 @@ ostree_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError **
                        "At least one PREFIX is required when deleting refs");
           goto out;
         }
+      else if (opt_create)
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "You must specify an existing ref when creating a new ref");
+          goto out;
+        }
+
       ret = do_ref (repo, NULL, cancellable, error);
     }
 
index bcebae9edffe9e05d4c79161a3a623493c35efd7..3d2290316a47638a2504158e6c24cbfb0ca355dc 100755 (executable)
@@ -65,4 +65,35 @@ ${CMD_PREFIX} ostree refs --repo=repo | wc -l > refscount.delete3
 assert_file_has_content refscount.delete3 "^3$"
 assert_not_file_has_content reflist '^test-1$'
 
+#Add a few more commits, to test --create
+${CMD_PREFIX} ostree --repo=repo commit --branch=ctest -m ctest -s ctest tree
+${CMD_PREFIX} ostree --repo=repo commit --branch=foo/ctest -m ctest -s ctest tree
+
+${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount
+assert_file_has_content refscount "^5$"
+
+if ${CMD_PREFIX} ostree --repo=repo refs --create=ctest-new; then
+    assert_not_reached "refs --create unexpectedly succeeded without specifying an existing ref!"
+fi
+if ${CMD_PREFIX} ostree --repo=repo refs ctest --create; then
+    assert_not_reached "refs --create unexpectedly succeeded without specifying the ref to create!"
+fi
+if ${CMD_PREFIX} ostree --repo=repo refs does-not-exist --create=ctest-new; then
+    assert_not_reached "refs --create unexpectedly succeeded for a prefix that doesn't exist!"
+fi
+if ${CMD_PREFIX} ostree --repo=repo refs ctest --create=foo; then
+    assert_not_reached "refs --create unexpectedly succeeded for a prefix that is already in use by a folder!"
+fi
+if ${CMD_PREFIX} ostree --repo=repo refs foo/ctest --create=ctest; then
+    assert_not_reached "refs --create unexpectedly succeeded in overwriting an existing prefix!"
+fi
+
+#Check to see if any uncleaned tmp files were created after failed --create
+${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create1
+assert_file_has_content refscount.create1 "^5$"
+
+${CMD_PREFIX} ostree --repo=repo refs ctest --create ctest-new
+${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create2
+assert_file_has_content refscount.create2 "^6$"
+
 echo "ok refs"